﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;

namespace SocketData
{
    //能够通过名称，来区取控制器，并执行相关的方法！
    class ControllerRunner
    {
        public List<Type> controllerTypes = new List<Type>();
        public Dictionary<string, Tuple<IHttpController, IEnumerable<MethodInfo>>> CtrlCache = new Dictionary<string, Tuple<IHttpController, IEnumerable<MethodInfo>>>();
        public string AssemblyName;
        public ControllerRunner(string assemblyName)
        {
            AssemblyName = assemblyName;
            foreach (Type type in Assembly.Load(assemblyName).GetTypes().Where(type => typeof(ApiController).IsAssignableFrom(type)))
            {
                controllerTypes.Add(type);
            }
        }
        private Tuple<IHttpController, IEnumerable<MethodInfo>> GetControllerInfo(string ctrlName)
        {
            Tuple<IHttpController, IEnumerable<MethodInfo>> ctrlInfo = null;
            ctrlName = AssemblyName + ".Controllers." + ctrlName;

            if (CtrlCache.TryGetValue(ctrlName, out ctrlInfo))
            {
                return ctrlInfo;
            }
            //没有缓存 ，则创建！
            Type controllerType = controllerTypes.FirstOrDefault(type => string.Compare(type.FullName, ctrlName, true) == 0);
            if (null != controllerType)
            {
                var ctrl = (ApiController)Activator.CreateInstance(controllerType);
                var methods = ctrl.GetType().GetMethods().Where(m => m.GetParameters().Length == 1);
                //.Select(m => { return m.GetParameters().Length == 1 ? m : null; }); //取出只有一个参数的方法
                Tuple<IHttpController, IEnumerable<MethodInfo>> tup = new Tuple<IHttpController, IEnumerable<MethodInfo>>(ctrl, methods);
                CtrlCache.Add(ctrlName, tup);
                return tup;
            }
            return null;
        }
        public object RunController(string ctrlName,string actionName,JObject para1)
        {
           var ctrlInfo=  GetControllerInfo(ctrlName);
            try
            {
                MethodInfo method = ctrlInfo.Item2.First(m => string.Compare(actionName, m.Name, true) == 0);
                List<object> parameters = new List<object>();
                parameters.Add(para1);
                return method.Invoke(ctrlInfo.Item1, parameters.ToArray());
            }
            catch (Exception)
            {
                return null;
            }
            
        }
    }
}
